home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JInternalFrame.java < prev    next >
Text File  |  1998-06-30  |  65KB  |  1,901 lines

  1. /* @(#)JInternalFrame.java    1.64 98/04/10
  2.  * 
  3.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  4.  * 
  5.  * This software is the confidential and proprietary information of Sun
  6.  * Microsystems, Inc. ("Confidential Information").  You shall not
  7.  * disclose such Confidential Information and shall use it only in
  8.  * accordance with the terms of the license agreement you entered into
  9.  * with Sun.
  10.  * 
  11.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  12.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  15.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  16.  * THIS SOFTWARE OR ITS DERIVATIVES.
  17.  * 
  18.  */
  19.  
  20. package com.sun.java.swing;
  21.  
  22. import java.awt.*;
  23. import java.awt.event.*;
  24. import java.beans.PropertyVetoException;
  25. import java.beans.PropertyChangeEvent;
  26. import java.util.EventListener;
  27. import com.sun.java.swing.border.Border;
  28. import com.sun.java.swing.event.InternalFrameEvent;
  29. import com.sun.java.swing.event.InternalFrameListener;
  30. import com.sun.java.swing.plaf.*;
  31.  
  32. import com.sun.java.accessibility.*;
  33.  
  34.  
  35. /**
  36.  * A lightweight object that provides many of the features of
  37.  * a native frame, including dragging, closing, becoming an icon,
  38.  * resizing, title display, and support for a menu bar. Generally,
  39.  * you create an instance and add it to a JDesktopPane. Look and
  40.  * feel specific-actions are then (automatically??) delegated to the 
  41.  * DesktopManager object maintained by the JDesktopPane (as set by
  42.  * the UI).
  43.  * <p>
  44.  * The JInternalFrame <code>contentPane</code> is where you add child components.
  45.  * So, to create a JInternalFrame that has a number of buttons arranged 
  46.  * with a BorderLayout object, you might do something like this:
  47.  * <PRE>
  48.  *    JComponent c = frame.getContentPane();
  49.  *    c.setLayoutManager(new BorderLayout());
  50.  *    c.add(new JButton(), BorderLayout.NORTH);
  51.  *    c.add(new JButton(), BorderLayout.CENTER);
  52.  * </PRE>
  53.  * The <code>contentPane</code> is actually managed by an instance of JRootPane,
  54.  * which also manages a <code>layoutPane</code>, <code>glassPane</code>, and 
  55.  * optional <code>menuBar</code> for the frame. Please see the JRootPane 
  56.  * documentation for a complete description of these components.
  57.  * <p>
  58.  * For the keyboard keys used by this component in the standard Look and
  59.  * Feel (L&F) renditions, see the
  60.  * <a href="doc-files/Key-Index.html#JInternalFrame">JInternalFrame</a> key assignments.
  61.  * <p>
  62.  * Warning: serialized objects of this class will not be compatible with
  63.  * future swing releases.  The current serialization support is appropriate 
  64.  * for short term storage or RMI between Swing1.0 applications.  It will
  65.  * not be possible to load serialized Swing1.0 objects with future releases
  66.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  67.  * baseline for the serialized form of Swing objects.
  68.  *
  69.  * @see JDesktopPane
  70.  * @see DesktopManager
  71.  * @see JDesktopIcon
  72.  * @see JRootPane
  73.  *
  74.  * @version 1.64 04/10/98
  75.  * @author David Kloba
  76.  * @beaninfo
  77.  *      attribute: isContainer true
  78.  *      attribute: containerDelegate getContentPane
  79.  *      description: A frame container which is contained within 
  80.  *                   another window.
  81.  */
  82. public class JInternalFrame extends JComponent implements 
  83.         Accessible, MouseListener, MouseMotionListener, WindowConstants, 
  84.         RootPaneContainer, ComponentListener
  85. {
  86.     /**
  87.      * The JRootPane instance that manages the <code>contentPane</code> 
  88.      * and optional <code>menuBar</code> for this frame, as well as the 
  89.      * <code>glassPane</code>.
  90.      *
  91.      * @see JRootPane
  92.      * @see RootPaneContainer
  93.      */
  94.     protected JRootPane rootPane;
  95.  
  96.     /**
  97.      * If true then calls to <code>add</code> and <code>setLayout</code>
  98.      * cause an exception to be thrown.  
  99.      */
  100.     protected boolean rootPaneCheckingEnabled = false;
  101.  
  102.     /** The frame can be closed. */
  103.     protected boolean closable;
  104.     /** The frame has been closed. */
  105.     protected boolean isClosed;
  106.     /** The frame can be expanded to the size of the desktop pane. */
  107.     protected boolean maximizable;
  108.     /** 
  109.      * The frame has been expanded to its maximum size.
  110.      * @see #maximizable
  111.      */
  112.     protected boolean isMaximum;   
  113.     /** 
  114.      * The frame can "iconized" (shrunk down and displayed as
  115.      * an icon-image). 
  116.      * @see JDesktopIcon
  117.      */
  118.     protected boolean iconable;
  119.     /** 
  120.      * The frame has been iconized. 
  121.      * @see #iconable
  122.      */
  123.     protected boolean isIcon;   
  124.     /** The frame's size can be changed. */
  125.     protected boolean resizable;
  126.     /** The frame is currently selected. */
  127.     protected boolean isSelected;
  128.     /** The icon shown in the top-left corner of the frame. */
  129.     protected Icon frameIcon;
  130.     /** The title displayed in the frame's title bar. */
  131.     protected String  title;
  132.     /** 
  133.      * The icon that is displayed when the frame is iconized.
  134.      * @see #iconable
  135.      */
  136.     protected JDesktopIcon desktopIcon;
  137.  
  138.     transient InternalFrameListener internalFrameListener;
  139.     private boolean opened;
  140.  
  141.     private int defaultCloseOperation = HIDE_ON_CLOSE;
  142.  
  143.     /** Bound property name. */
  144.     public final static String CONTENT_PANE_PROPERTY = "contentPane";
  145.     /** Bound property name. */
  146.     public final static String MENU_BAR_PROPERTY = "menuBar";
  147.     /** Bound property name. */
  148.     public final static String TITLE_PROPERTY = "title";
  149.     /** Bound property name. */
  150.     public final static String LAYERED_PANE_PROPERTY = "layeredPane";
  151.     /** Bound property name. */
  152.     public final static String ROOT_PANE_PROPERTY = "rootPane";
  153.     /** Bound property name. */
  154.     public final static String GLASS_PANE_PROPERTY = "glassPane";
  155.  
  156.     /** Constrained property name indicated that this frame has selected status. */
  157.     public final static String IS_SELECTED_PROPERTY = "isSelected";
  158.     /** Constrained property name indicating that the frame is closed. */
  159.     public final static String IS_CLOSED_PROPERTY = "isClosed";
  160.     /** Constrained property name indicating that the frame is maximized. */
  161.     public final static String IS_MAXIMUM_PROPERTY = "isMaximum";
  162.     /** Constrained property name indicating that the frame is iconified. */
  163.     public final static String IS_ICON_PROPERTY = "isIcon";
  164.  
  165.     /** 
  166.      * Creates a non-resizable, non-closable, non-maximizable,
  167.      * non-iconifiable JInternalFrame with no title.
  168.      */
  169.     public JInternalFrame() {
  170.         this("", false, false, false, false);
  171.     }
  172.  
  173.     /** 
  174.      * Creates a non-resizable, non-closable, non-maximizable,
  175.      * non-iconifiable JInternalFrame with the specified title.
  176.      *
  177.      * @param title  the String to display in the title bar.
  178.      */
  179.     public JInternalFrame(String title) {
  180.         this(title, false, false, false, false);
  181.     }
  182.  
  183.     /** 
  184.      * Creates a non-closable, non-maximizable, non-iconifiable 
  185.      * JInternalFrame with the specified title and with resizability 
  186.      * specified.
  187.      *
  188.      * @param title      the String to display in the title bar.
  189.      * @param resizable  if true, the frame can be resized
  190.      */
  191.     public JInternalFrame(String title, boolean resizable) {
  192.         this(title, resizable, false, false, false);
  193.     }
  194.  
  195.     /** 
  196.      * Creates a non-maximizable, non-iconifiable JInternalFrame with the
  197.      * specified title and with resizability and closability specified.
  198.      *
  199.      * @param title      the String to display in the title bar.
  200.      * @param resizable  if true, the frame can be resized
  201.      * @param closable   if true, the frame can be closed
  202.      */
  203.     public JInternalFrame(String title, boolean resizable, boolean closable) {
  204.         this(title, resizable, closable, false, false);
  205.     }
  206.  
  207.     /** 
  208.      * Creates a non-iconifiable JInternalFrame with the specified title 
  209.      * and with resizability, closability, and maximizability specified.
  210.      *
  211.      * @param title       the String to display in the title bar.
  212.      * @param resizable   if true, the frame can be resized
  213.      * @param closable    if true, the frame can be closed
  214.      * @param maximizable if true, the frame can be maximized
  215.      */
  216.     public JInternalFrame(String title, boolean resizable, boolean closable,
  217.                           boolean maximizable) {
  218.         this(title, resizable, closable, maximizable, false);
  219.     }
  220.  
  221.     /** 
  222.      * Creates a JInternalFrame with the specified title and 
  223.      * with resizability, closability, maximizability, and iconifiability
  224.      * specified.
  225.      *
  226.      * @param title       the String to display in the title bar.
  227.      * @param resizable   if true, the frame can be resized
  228.      * @param closable    if true, the frame can be closed
  229.      * @param maximizable if true, the frame can be maximized
  230.      * @param iconifiable if true, the frame can be iconified
  231.      */
  232.     public JInternalFrame(String title, boolean resizable, boolean closable, 
  233.                                 boolean maximizable, boolean iconifiable) {
  234.         
  235.         setRootPane(createRootPane());
  236.         setLayout(new BorderLayout());
  237.         this.title = title;
  238.         this.resizable = resizable;
  239.         this.closable = closable;
  240.         this.maximizable = maximizable;
  241.         isMaximum = false;
  242.         this.iconable = iconifiable;                         
  243.         isIcon = false;
  244.         updateUI();
  245.         setRootPaneCheckingEnabled(true);
  246.         desktopIcon = new JDesktopIcon(this);
  247.         if (isVisible()) {
  248.             postInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
  249.             opened = true;
  250.         }
  251.     }
  252.  
  253.     /** 
  254.      * Called by the constructor to set up the JRootPane.
  255.      * @see JRootPane
  256.      */
  257.     protected JRootPane createRootPane() {
  258.         return new JRootPane();
  259.     }
  260.  
  261.     /**
  262.      * Returns the L&F object that renders this component.
  263.      *
  264.      * @return the InternalFrameUI object that renders this component
  265.      */
  266.     public InternalFrameUI getUI() {
  267.         return (InternalFrameUI)ui;
  268.     }
  269.  
  270.     /**
  271.      * Sets the UI delegate for this JInternalFrame.
  272.      * @beaninfo
  273.      *     expert: true
  274.      *     description: The InternalFrameUI implementation that 
  275.      *                  defines the labels look and feel.
  276.      */
  277.     public void setUI(InternalFrameUI ui) {
  278.         boolean checkingEnabled = isRootPaneCheckingEnabled();
  279.         try {
  280.             setRootPaneCheckingEnabled(false);
  281.             super.setUI(ui);
  282.         }
  283.         finally {
  284.             setRootPaneCheckingEnabled(checkingEnabled);
  285.         }
  286.     }
  287.  
  288.     /**
  289.      * Notification from the UIManager that the L&F has changed. 
  290.      * Replaces the current UI object with the latest version from the 
  291.      * UIManager.
  292.      *
  293.      * @see JComponent#updateUI
  294.      */
  295.     public void updateUI() {
  296.         setUI((InternalFrameUI)UIManager.getUI(this));
  297.         invalidate();
  298.         if (desktopIcon != null) {
  299.             desktopIcon.updateUIWhenHidden();
  300.         }
  301.     }
  302.  
  303.     /* This method is called if updateUI was called on the associated
  304.      * JDesktopIcon.  It's necessary to avoid infinite recursion.
  305.      */
  306.     void updateUIWhenHidden() {
  307.         setUI((InternalFrameUI)UIManager.getUI(this));
  308.         invalidate();
  309.         Component[] children = getComponents();
  310.         if (children != null) {
  311.             for(int i = 0; i < children.length; i++) {
  312.                 SwingUtilities.updateComponentTreeUI(children[i]);
  313.             }
  314.         }
  315.     }
  316.  
  317.  
  318.     /**
  319.      * Returns the name of the L&F class that renders this component.
  320.      *
  321.      * @return "InternalFrameUI"
  322.      * @see JComponent#getUIClassID
  323.      * @see UIDefaults#getUI
  324.      * @beaninfo
  325.      *     description: UIClassID
  326.      */
  327.     public String getUIClassID() {
  328.         return "InternalFrameUI";
  329.     }
  330.  
  331.     /**
  332.      * Returns whether calls to <code>add</code> and 
  333.      * <code>setLayout</code> cause an exception to be thrown. 
  334.      *
  335.      * @return true if <code>add</code> and <code>setLayout</code> 
  336.      *         are checked
  337.      * @see #addImpl
  338.      * @see #setLayout
  339.      * @see #setRootPaneCheckingEnabled
  340.      */
  341.     protected boolean isRootPaneCheckingEnabled() {
  342.         return rootPaneCheckingEnabled;
  343.     }
  344.  
  345.  
  346.     /**
  347.      * Determines whether calls to <code>add</code> and 
  348.      * <code>setLayout</code> cause an exception to be thrown. 
  349.      * 
  350.      * @param enabled  a boolean value, true if checking is to be
  351.      *        enabled, which cause the exceptions to be thrown
  352.      *
  353.      * @see #addImpl
  354.      * @see #setLayout
  355.      * @see #isRootPaneCheckingEnabled
  356.      */
  357.     protected void setRootPaneCheckingEnabled(boolean enabled) {
  358.         rootPaneCheckingEnabled = enabled;
  359.     }
  360.  
  361.  
  362.     /**
  363.      * Creates a runtime exception with a message like:
  364.      * <pre>
  365.      * "Do not use JFrame.add() use JFrame.getContentPane().add() instead"
  366.      * </pre>
  367.      *
  368.      * @param op  a String indicating the attempted operation. In the
  369.      *            example above, the operation string is "add"
  370.      */
  371.     private Error createRootPaneException(String op) {
  372.         String type = getClass().getName();
  373.         return new Error(
  374.             "Do not use " + type + "." + op + "() use " 
  375.                           + type + ".getContentPane()." + op + "() instead");
  376.     }
  377.  
  378.  
  379.     /**
  380.      * By default, children may not be added directly to a this component,
  381.      * they must be added to its contentPane instead.  For example:
  382.      * <pre>
  383.      * thisComponent.getContentPane().add(child)
  384.      * </pre>
  385.      * An attempt to add to directly to this component will cause an
  386.      * runtime exception to be thrown.  Subclasses can disable this
  387.      * behavior.
  388.      * 
  389.      * @see #setRootPaneCheckingEnabled
  390.      * @exception Error if called with rootPaneChecking true
  391.      */
  392.     protected void addImpl(Component comp, Object constraints, int index) 
  393.     {
  394.         if(isRootPaneCheckingEnabled()) {
  395.             throw createRootPaneException("add");
  396.         }
  397.         else {
  398.             super.addImpl(comp, constraints, index);
  399.         }
  400.     }
  401.  
  402.  
  403.     /**
  404.      * By default the layout of this component may not be set,
  405.      * the layout of its contentPane should be set instead.  
  406.      * For example:
  407.      * <pre>
  408.      * thiComponent.getContentPane().setLayout(new BorderLayout())
  409.      * </pre>
  410.      * An attempt to set the layout of this component will cause an
  411.      * runtime exception to be thrown.  Subclasses can disable this
  412.      * behavior.
  413.      * 
  414.      * @see #setRootPaneCheckingEnabled
  415.      * @exception Error if called with rootPaneChecking true
  416.      */
  417.     public void setLayout(LayoutManager manager) {
  418.         if(isRootPaneCheckingEnabled()) {
  419.             throw createRootPaneException("setLayout");
  420.         }
  421.         else {
  422.             super.setLayout(manager);
  423.         }
  424.     }
  425.  
  426.  
  427. //////////////////////////////////////////////////////////////////////////
  428. /// Property Methods
  429. //////////////////////////////////////////////////////////////////////////
  430.  
  431.     /**
  432.      * Returns the current JMenuBar for this JInternalFrame, or null
  433.      * if no menu bar has been set.
  434.      *
  435.      * @return  the JMenuBar used by this frame
  436.      * @see #setMenuBar
  437.      */
  438.     public JMenuBar getMenuBar() {
  439.         return getRootPane().getMenuBar();
  440.     }
  441.  
  442.     /**
  443.      * Sets the JMenuBar for this JInternalFrame.
  444.      *
  445.      * @param m  the JMenuBar to use in this frame
  446.      * @see #getMenuBar
  447.      * @beaninfo
  448.      *     preferred: true
  449.      *     description: The menubar for accessing pulldown menus 
  450.      *                  from this frame.
  451.      */
  452.     public void setMenuBar(JMenuBar m) {
  453.         JMenuBar oldValue = getMenuBar();
  454.         getRootPane().setMenuBar(m);
  455.         firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);     
  456.     }
  457.  
  458.  
  459.     // @see RootPaneContainer#getContentPane
  460.     public Container getContentPane() {
  461.         return getRootPane().getContentPane();
  462.     }
  463.  
  464.  
  465.     /**
  466.      * Sets this JInternalFrame's content pane.
  467.      * 
  468.      * @param c the Container to use for the contents of this JInternalFrame
  469.      * @exception java.awt.IllegalComponentStateException (a runtime
  470.      *            exception) if the content pane parameter is null
  471.      * @see RootPaneContainer#getContentPane
  472.      * @beaninfo
  473.      *     bound: true
  474.      *     hidden: true
  475.      *     description: The client area of the frame where child 
  476.      *                  components are normally inserted.
  477.      */
  478.     public void setContentPane(Container c) {
  479.         Container oldValue = getContentPane();
  480.         getRootPane().setContentPane(c);
  481.         firePropertyChange(CONTENT_PANE_PROPERTY, oldValue, c);
  482.     }
  483.  
  484.  
  485.     // @see RootPaneContainer#setLayeredPane
  486.     public JLayeredPane getLayeredPane() { 
  487.         return getRootPane().getLayeredPane(); 
  488.     }
  489.  
  490.  
  491.     /**
  492.      * Sets this JInternalFrame's layered pane.
  493.      *
  494.      * @exception java.awt.IllegalComponentStateException (a runtime
  495.      *            exception) if the layered pane parameter is null
  496.      * @see RootPaneContainer#setLayeredPane
  497.      * @beaninfo
  498.      *     hidden: true
  499.      *     bound: true
  500.      *     description: The pane which holds the various desktop layers.
  501.      */
  502.     public void setLayeredPane(JLayeredPane layered) {
  503.         JLayeredPane oldValue = getLayeredPane();
  504.         getRootPane().setLayeredPane(layered);
  505.         firePropertyChange(LAYERED_PANE_PROPERTY, oldValue, layered);   
  506.     }
  507.  
  508.  
  509.     // @see RootPaneContainer#setGlassPane
  510.     public Component getGlassPane() { 
  511.         return getRootPane().getGlassPane(); 
  512.     }
  513.  
  514.  
  515.     /**
  516.      * Sets this JInternalFrame's glass pane.
  517.      * @see RootPaneContainer#getGlassPane
  518.      * @beaninfo
  519.      *     hidden: true
  520.      *     description: A transparent pane used for menu rendering.
  521.      */
  522.     public void setGlassPane(Component glass) {
  523.         Component oldValue = getGlassPane();
  524.         getRootPane().setGlassPane(glass);
  525.         firePropertyChange(GLASS_PANE_PROPERTY, oldValue, glass);       
  526.     }
  527.  
  528.  
  529.     // @see RootPaneContainer#getRootPane
  530.     public JRootPane getRootPane() { 
  531.         return rootPane; 
  532.     }
  533.  
  534.  
  535.     /**
  536.      * Set the rootPane property.  This method is called by the constructor.
  537.      * @beaninfo
  538.      *     hidden: true
  539.      *     beaninfo: The rootPane used by this frame.
  540.      */
  541.     protected void setRootPane(JRootPane root) {
  542.         if(rootPane != null) {
  543.             remove(rootPane);
  544.         }
  545.         JRootPane oldValue = getRootPane();
  546.         rootPane = root;
  547.         if(rootPane != null) {
  548.             boolean checkingEnabled = isRootPaneCheckingEnabled();
  549.             try {
  550.                 setRootPaneCheckingEnabled(false);
  551.                 add(rootPane, BorderLayout.CENTER);
  552.             }
  553.             finally {
  554.                 setRootPaneCheckingEnabled(checkingEnabled);
  555.             }
  556.         }
  557.         firePropertyChange(ROOT_PANE_PROPERTY, oldValue, root); 
  558.     }
  559.  
  560.  
  561.     /**
  562.      * Set the visible state of the object.
  563.      *
  564.      * @param b if true, shows this object; otherwise, hides it 
  565.      */
  566.     public void setVisible(boolean b) {
  567.         super.setVisible(b);
  568.         // If first time shown, generate InternalFrameOpened event
  569.         if (!opened) {
  570.             postInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
  571.             opened = true;
  572.         }
  573.     }
  574.  
  575.     /** 
  576.      * Set that this JInternalFrame can be closed by some user action.
  577.      * @param b a boolean value, where true means the frame can be closed 
  578.      * @beaninfo
  579.      *     preferred: true
  580.      *     description: Indicates whether this frame can be closed.
  581.      */
  582.     public void setClosable(boolean b) {
  583.         closable = b;
  584.     }
  585.  
  586.     /** 
  587.      * Returns whether this JInternalFrame be closed by some user action. 
  588.      * @return true if the frame can be closed 
  589.      */
  590.     public boolean isClosable() {
  591.         return closable;
  592.     }
  593.  
  594.     /** 
  595.      * Returns whether this JInternalFrame is currently closed. 
  596.      * @return true if the frame is closed 
  597.      */
  598.     public boolean isClosed() {
  599.         return isClosed;
  600.     }
  601.  
  602.     /** 
  603.      * Calling this method with a value of <code>true</code> to close
  604.      * the frame.
  605.      *
  606.      * @param b a boolean, where true means "close the frame"
  607.      * @exception PropertyVetoException when the attempt to set the 
  608.      *            property is vetoed by the receiver.
  609.      * @beaninfo
  610.      *     constrained: true
  611.      *     description: Indicates that the frame has been closed.
  612.      */
  613.     public void setClosed(boolean b) throws PropertyVetoException {
  614.         if (isClosed == b) {
  615.             return;
  616.         }
  617.  
  618.         Boolean oldValue = isClosed ? Boolean.TRUE : Boolean.FALSE; 
  619.         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  620.         fireVetoableChange(IS_CLOSED_PROPERTY, oldValue, newValue);
  621.         isClosed = b;
  622.         if (isClosed) {
  623.             /* Dispatch a closed event to any listeners.  We can't post
  624.              * an event since firing IS_CLOSED_PROPERTY causes this
  625.              * frame to be removed from its parent, which causes any
  626.              * of its events on the EventQueue to get purged.
  627.              */
  628.             synchronized (this) {
  629.                 if (internalFrameListener != null) {
  630.                     InternalFrameEvent e = new InternalFrameEvent(
  631.                         this, InternalFrameEvent.INTERNAL_FRAME_CLOSED);
  632.                     dispatchEvent(e);
  633.                 }
  634.             }
  635.             opened = false;
  636.         } else if (!opened) {
  637.             postInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
  638.             opened = true;
  639.         }
  640.         firePropertyChange(IS_CLOSED_PROPERTY, oldValue, newValue);
  641.     }
  642.  
  643.     /** 
  644.      * Set that the JInternalFrame can be resized by some user action.
  645.      *
  646.      * @param b  a boolean, where true means the frame can be resized 
  647.      * @beaninfo
  648.      *     preferred: true
  649.      *     description: Determines whether the frame can be resized 
  650.      *                  by the user.
  651.      */
  652.     public void setResizable(boolean b) {
  653.         resizable = b;
  654.     }
  655.  
  656.     /** 
  657.      * Returns whether the JInternalFrame can be resized by some user action.
  658.      *
  659.      * @return true if the frame can be resized
  660.      */ 
  661.     public boolean isResizable() {
  662.         // don't allow resizing when maximized.
  663.         return isMaximum ? false : resizable; 
  664.     }
  665.  
  666.     /** 
  667.      * Set that the JInternalFrame can be made an icon by some user action. 
  668.      *
  669.      * @param b  a boolean, where true means the frame can be iconified 
  670.      * @beaninfo:
  671.      *     preferred: true
  672.      *     bound: false
  673.      *     description: Determines whether this frame can be iconified.
  674.      */
  675.     public void setIconifiable(boolean b) {
  676.         iconable = b;
  677.     }
  678.  
  679.     /** 
  680.      * Returns whether the JInternalFrame can be iconified by some user action.
  681.      *
  682.      * @return true if the frame can be iconified
  683.      */ 
  684.     public boolean isIconifiable() {
  685.         return iconable; 
  686.     }
  687.  
  688.     /** 
  689.      * Returns whether the JInternalFrame is currently iconified.
  690.      *
  691.      * @return true if the frame is iconified
  692.      */ 
  693.     public boolean isIcon() {
  694.         return isIcon;
  695.     }
  696.  
  697.     /** 
  698.      * Iconizes and deconizes the frame.
  699.      *
  700.      * @param b a boolean, where true means to iconify the frame and
  701.      *          false means to deiconify it
  702.      * @exception PropertyVetoException when the attempt to set the 
  703.      *            property is vetoed by the receiver.
  704.      * @beaninfo
  705.      *     constrained: true
  706.      *     description: The image displayed when this frame is minimized.
  707.      */
  708.     public void setIcon(boolean b) throws PropertyVetoException {
  709.         if (isIcon == b) {
  710.             return;
  711.         }
  712.  
  713.         Boolean oldValue = isIcon ? Boolean.TRUE : Boolean.FALSE; 
  714.         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  715.         fireVetoableChange(IS_ICON_PROPERTY, oldValue, newValue);
  716.         isIcon = b;
  717.         firePropertyChange(IS_ICON_PROPERTY, oldValue, newValue);
  718.         postInternalFrameEvent(
  719.             b ? InternalFrameEvent.INTERNAL_FRAME_ICONIFIED :
  720.                 InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED);
  721.     }
  722.  
  723.     /** 
  724.      * Set that the JInternalFrame can be maximized by some user action.
  725.      *
  726.      * @param b a boolean  where true means the frame can be maximized 
  727.      * @beaninfo
  728.      *     preferred: true
  729.      *     description: Determines whether this frame can be maximized.
  730.      */
  731.     public void setMaximizable(boolean b) {
  732.         maximizable = b;
  733.     }
  734.  
  735.     /** 
  736.      * Returns whether the JInternalFrame can be maximized by some user action.
  737.      *
  738.      * @return true if the frame can be maximized 
  739.      */
  740.     public boolean isMaximizable() {
  741.         return maximizable; 
  742.     }
  743.  
  744.     /** 
  745.      * Returns whether the JInternalFrame is currently maximized.
  746.      *
  747.      * @return true if the frame is maximized 
  748.      */
  749.     public boolean isMaximum() {
  750.         return isMaximum;
  751.     }
  752.  
  753.     /**
  754.      * Maximizes and restores the frame.  A maximized frame is resized to
  755.      * fully fit the JDesktopPane area associated with the JInternalFrame.
  756.      * A restored frame's size is set to the JInternalFrame's actual size.
  757.      *
  758.      * @param b  a boolean, where true maximizes the frame and false
  759.      *           restores it
  760.      * @exception PropertyVetoException when the attempt to set the 
  761.      *            property is vetoed by the receiver.
  762.      * @beaninfo
  763.      *     constrained: true
  764.      *     description: Indicates whether the frame is maximized.
  765.      */
  766.     public void setMaximum(boolean b) throws PropertyVetoException {
  767.         if (isMaximum == b) {
  768.             return;
  769.         }
  770.  
  771.         Boolean oldValue = isMaximum ? Boolean.TRUE : Boolean.FALSE;
  772.         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  773.         fireVetoableChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
  774.         isMaximum = b;
  775.         if (b) {
  776.             getDesktopPane().addComponentListener(this);
  777.         } else {
  778.             JDesktopPane pane = getDesktopPane();
  779.             if (pane != null) {
  780.                 pane.removeComponentListener(this);
  781.             }
  782.         }
  783.         firePropertyChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
  784.     }
  785.  
  786.     /**
  787.      * Returns the title of the JInternalFrame.
  788.      *
  789.      * @return a String containing the frame's title
  790.      * @see setTitle
  791.      */
  792.     public String getTitle() {
  793.         return title;
  794.     }
  795.  
  796.     /** 
  797.      * Sets the JInternalFrame title. 
  798.      *
  799.      * @param title  the String to display in the title bar
  800.      * @see #title
  801.      * @beaninfo:
  802.      *     preferred: true
  803.      *     bound: true
  804.      *     description: The text displayed in the title bar.
  805.      */
  806.     public void setTitle(String title) {
  807.         String oldValue = this.title;
  808.         this.title = title;
  809.         firePropertyChange(TITLE_PROPERTY, oldValue, title);
  810.     }
  811.  
  812.     /**
  813.      * Selects and deselects the JInternalFrame.
  814.      * A JInternalFrame normally draws it's title bar differently if it is
  815.      * the selected frame, which indicates to the user that this 
  816.      * internalFrame has the focus.
  817.      *
  818.      * @param selected  a boolean, where true means the frame is selected
  819.      *                  (currently active) and false means it is not
  820.      * @exception PropertyVetoException when the attempt to set the 
  821.      *            property is vetoed by the receiver.
  822.      * @beaninfo
  823.      *     constrained: true
  824.      *     description: Indicates whether this frame is currently 
  825.      *                  the active frame.
  826.      */
  827.     public void setSelected(boolean selected) throws PropertyVetoException {
  828.         if (isSelected == selected) {
  829.             return;
  830.         }
  831.  
  832.         Boolean oldValue = isSelected ? Boolean.TRUE : Boolean.FALSE;
  833.         Boolean newValue = selected ? Boolean.TRUE : Boolean.FALSE;
  834.         fireVetoableChange(IS_SELECTED_PROPERTY, oldValue, newValue);
  835.         isSelected = selected;
  836.  
  837.         Component glassPane = getGlassPane();
  838.         if (isSelected) {
  839.             // Turn off mouse event forwarding (see below).
  840.             glassPane.removeMouseListener(this);
  841.             glassPane.removeMouseMotionListener(this);
  842.             glassPane.setVisible(false);
  843.         } else {
  844.             // Forward mouse events on to UI, so it can activate this frame.
  845.             glassPane.addMouseListener(this);
  846.             glassPane.addMouseMotionListener(this);
  847.             glassPane.setVisible(true);
  848.         }
  849.  
  850.         firePropertyChange(IS_SELECTED_PROPERTY, oldValue, newValue);
  851.         postInternalFrameEvent(
  852.             isSelected ? InternalFrameEvent.INTERNAL_FRAME_ACTIVATED :
  853.                          InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED);
  854.         repaint();
  855.     }
  856.  
  857.     /**
  858.      * Returns whether the JInternalFrame is the currently "selected" or
  859.      * active frame.
  860.      *
  861.      * @return true if the frame is currently selected (active)
  862.      * @see #setSelected
  863.      */
  864.     public boolean isSelected() {
  865.         return isSelected;
  866.     } 
  867.  
  868.     /** 
  869.      * Sets an image to be displayed in the titlebar of the frame (usually
  870.      * in the top-left corner).
  871.      * This image is not the <code>desktopIcon</code> object, which 
  872.      * is the image displayed in the JDesktop when the frame is iconified.
  873.      *
  874.      * @param icon the Icon to display in the title bar
  875.      * @see #desktopIcon
  876.      * @beaninfo
  877.      *     description: The icon shown in the top-left corner of the frame.
  878.      */
  879.     public void setFrameIcon(Icon icon) {
  880.         frameIcon = icon;
  881.     }
  882.  
  883.     /** 
  884.      * Returns the image displayed in the title bar of the frame (usually
  885.      * in the top-left corner).
  886.      * 
  887.      * @return the Icon displayed in the title bar
  888.      */
  889.     public Icon getFrameIcon()  {
  890.         return frameIcon;
  891.     }
  892.  
  893.     /**
  894.      * Get the background color of this object.
  895.      *
  896.      * @return the background color, if supported, of the object; 
  897.      * otherwise, null
  898.      */
  899.     public Color getBackground() {
  900.         return getContentPane().getBackground();
  901.     }
  902.  
  903.     /**
  904.      * Set the background color of this object.
  905.      * (For transparency, see <code>isOpaque</code>.)
  906.      *
  907.      * @param c the new Color for the background
  908.      * @see #isOpaque
  909.      */
  910.     public void setBackground(Color c) {
  911.         getContentPane().setBackground(c);
  912.     }
  913.  
  914.     /**
  915.      * Get the foreground color of this object.
  916.      *
  917.      * @return the foreground color, if supported, of the object; 
  918.      * otherwise, null
  919.      */
  920.     public Color getForeground() {
  921.         return getContentPane().getForeground();
  922.     }
  923.  
  924.     /**
  925.      * Set the foreground color of this object.
  926.      *
  927.      * @param c the new Color for the foreground
  928.      */
  929.     public void setForeground(Color c) {
  930.         getContentPane().setForeground(c);
  931.     }
  932.  
  933.     /** Convenience method that moves this component to position 0 if it's 
  934.       * parent is a JLayeredPane.
  935.       */
  936.     public void moveToFront() {
  937.         if(getParent() != null && getParent() instanceof JLayeredPane) {
  938.             JLayeredPane l =  (JLayeredPane)getParent();
  939.             l.moveToFront(this);
  940.         }
  941.     }
  942.  
  943.     /** Convenience method that moves this component to position -1 if it's 
  944.       * parent is a JLayeredPane.
  945.       */
  946.     public void moveToBack() {
  947.         if(getParent() != null && getParent() instanceof JLayeredPane) {
  948.             JLayeredPane l =  (JLayeredPane)getParent();
  949.             l.moveToBack(this);
  950.         }
  951.     }
  952.  
  953.     /** 
  954.      * Convenience method for setting the layer attribute of this component.
  955.      *
  956.      * @param layer  an Integer object specifying this frame's desktop layer
  957.      * @see JLayeredPane
  958.      * @beaninfo
  959.      *     expert: true
  960.      *     description: Specifies what desktop layer is used.
  961.      */
  962.     public void setLayer(Integer layer) {
  963.         if(getParent() != null && getParent() instanceof JLayeredPane) {
  964.             // Normally we want to do this, as it causes the LayeredPane
  965.             // to draw properly.
  966.             JLayeredPane p = (JLayeredPane)getParent();
  967.             p.setLayer(this, layer.intValue(), p.getPosition(this));
  968.         } else {
  969.              // Try to do the right thing
  970.              JLayeredPane.putLayer(this, layer.intValue());
  971.              if(getParent() != null)
  972.                 getParent().repaint(_bounds.x, _bounds.y, 
  973.                                     _bounds.width, _bounds.height);
  974.         }
  975.     }
  976.  
  977.     /** Convenience method for getting the layer attribute of this component.
  978.      *
  979.      * @return  an Integer object specifying this frame's desktop layer
  980.      * @see JLayeredPane
  981.       */
  982.     public int getLayer() {
  983.         return JLayeredPane.getLayer(this);
  984.     }
  985.  
  986.     /** Convenience method that searchs the anscestor heirarchy for a 
  987.       * JDesktop instance. If JInternalFrame finds none, the desktopIcon
  988.       * tree is searched.
  989.       *
  990.       * @return the JDesktopPane this frame belongs to, or null if none
  991.       *         is found
  992.       */
  993.     public JDesktopPane getDesktopPane() { 
  994.         Container p;
  995.  
  996.         // Search upward for desktop
  997.         p = getParent();
  998.         while(p != null && !(p instanceof JDesktopPane))
  999.             p = p.getParent();
  1000.         
  1001.         if(p == null) {
  1002.            // search it's icon parent for desktop
  1003.            p = getDesktopIcon().getParent();
  1004.            while(p != null && !(p instanceof JDesktopPane))
  1005.                 p = p.getParent();
  1006.         }
  1007.  
  1008.         return (JDesktopPane)p; 
  1009.     }
  1010.  
  1011.     /**
  1012.      * Sets the JDesktopIcon associated with this JInternalFrame.
  1013.      *
  1014.      * @param d the JDesktopIcon to display on the desktop
  1015.      * @see #desktopIcon
  1016.      * @beaninfo
  1017.      *     description: The icon shown when this frame is minimized.
  1018.      */
  1019.     public void setDesktopIcon(JDesktopIcon d) { desktopIcon = d; }
  1020.  
  1021.     /** 
  1022.      * Returns the JDesktopIcon used when this JInternalFrame is iconified.
  1023.      *
  1024.      * @return the JDesktopIcon displayed on the desktop
  1025.      * @see #desktopIcon
  1026.      */
  1027.     public JDesktopIcon getDesktopIcon() { 
  1028.         return desktopIcon; 
  1029.     }
  1030.  
  1031.  
  1032.     /*
  1033.      * Creates a new EventDispatchThread to dispatch events from. This
  1034.      * method returns when stopModal is invoked.
  1035.      */
  1036.     synchronized void startModal() {
  1037.         try {
  1038.             // can't use instanceof EventDispatchThread because the class isn't public
  1039.             if (Thread.currentThread().getClass().getName().endsWith("EventDispatchThread")) {
  1040.                 EventQueue theQueue = getToolkit().getSystemEventQueue();
  1041.                 while (isVisible()) {
  1042.                     // This is essentially the body of EventDispatchThread
  1043.                     AWTEvent event = theQueue.getNextEvent();
  1044.                     Object src = event.getSource();
  1045.                     // can't call theQueue.dispatchEvent, so I pasted it's body here
  1046.                     /*if (event instanceof ActiveEvent) {
  1047.                       ((ActiveEvent) event).dispatch();
  1048.                       } else */ if (src instanceof Component) {
  1049.                           ((Component) src).dispatchEvent(event);
  1050.                       } else if (src instanceof MenuComponent) {
  1051.                           ((MenuComponent) src).dispatchEvent(event);
  1052.                       } else {
  1053.                           System.err.println("unable to dispatch event: " + event);
  1054.                       }
  1055.                 }
  1056.             } else
  1057.                 while (isVisible())
  1058.                     wait();
  1059.         } catch(InterruptedException e){}
  1060.     }
  1061.   
  1062.     /*
  1063.      * Stops the event dispatching loop created by a previous call to
  1064.      * <code>startModal</code>.
  1065.      */
  1066.     synchronized void stopModal() {
  1067.         notifyAll();
  1068.     }
  1069.   
  1070.     /**
  1071.      * Moves and resizes this component.  Unlike other components,
  1072.      * this implementation also forces re-layout, so that frame
  1073.      * decorations such as the title bar are always redisplayed.
  1074.      *
  1075.      * @param x  an int giving the component's new horizontal position
  1076.      *           measured in pixels from the left of its container
  1077.      * @param y  an int giving the component's new vertical position,
  1078.      *           measured in pixels from the bottom of its container
  1079.      * @param width  an int giving the component's new width in pixels
  1080.      * @param height an int giving the component's new height in pixels
  1081.      */
  1082.     public void reshape(int x, int y, int width, int height) {
  1083.         super.reshape(x, y, width, height);
  1084.         validate();
  1085.         repaint();
  1086.     }
  1087.  
  1088. ///////////////////////////
  1089. // Frame/Window equivalents
  1090. ///////////////////////////
  1091.  
  1092.     /**
  1093.      * Adds the specified internal frame listener to receive internal frame events from
  1094.      * this internal frame.
  1095.      * @param l the internal frame listener
  1096.      */ 
  1097.     public synchronized void addInternalFrameListener(InternalFrameListener l) {
  1098.         internalFrameListener = MyEventMulticaster.add(
  1099.             internalFrameListener, l);
  1100.         enableEvents(0);   // turn on the newEventsOnly flag in Component.
  1101.     }
  1102.  
  1103.     /**
  1104.      * Removes the specified internal frame listener so that it no longer
  1105.      * receives internal frame events from this internal frame.
  1106.      * @param l the internal frame listener
  1107.      */ 
  1108.     public synchronized void removeInternalFrameListener(InternalFrameListener l) {
  1109.         internalFrameListener = MyEventMulticaster.remove(
  1110.             internalFrameListener, l);
  1111.     }
  1112.  
  1113.     private synchronized void postInternalFrameEvent(int id) {
  1114.         if (internalFrameListener != null) {
  1115.             InternalFrameEvent e = new InternalFrameEvent(this, id);
  1116.             /* Try posting event, but don't bother if there's a 
  1117.              * SecurityManager since in most environments it will
  1118.              * display a harmless stacktrace when creating the
  1119.              * SecurityException which developers find scary. 
  1120.              */
  1121.             if (JInternalFrame.class.getClassLoader() == null) {
  1122.                 try {
  1123.                     Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
  1124.                     return;
  1125.                 } catch (SecurityException se) {
  1126.                     // Use dispatchEvent instead.
  1127.                 }
  1128.             }
  1129.             dispatchEvent(e);
  1130.         }
  1131.     }
  1132.  
  1133.     private void doDefaultCloseAction() {
  1134.         switch(defaultCloseOperation) {
  1135.           case HIDE_ON_CLOSE:
  1136.               try {
  1137.                   setClosed(true);
  1138.               } catch (PropertyVetoException pve) {}
  1139.               break;
  1140.           case DISPOSE_ON_CLOSE:
  1141.               try {
  1142.                   setClosed(true);
  1143.                   dispose();  // only executes if close wasn't vetoed.
  1144.               } catch (PropertyVetoException pve) {}
  1145.               break;
  1146.           case DO_NOTHING_ON_CLOSE:
  1147.           default: 
  1148.               break;
  1149.         }
  1150.     }
  1151.  
  1152.     /**
  1153.      * Processes events on this internal frame. If the event has a
  1154.      * InternalFrameEvent id, it notifies its internalFrameListener, else it 
  1155.      * invokes its superclass's processEvent.
  1156.      * @param e the event
  1157.      */
  1158.     protected void processEvent(AWTEvent e) {
  1159.         synchronized (this) { 
  1160.             if (internalFrameListener != null) {
  1161.                 switch(e.getID()) {
  1162.                   case InternalFrameEvent.INTERNAL_FRAME_OPENED:
  1163.                       internalFrameListener.internalFrameOpened(
  1164.                           (InternalFrameEvent)e);
  1165.                       return;
  1166.                   case InternalFrameEvent.INTERNAL_FRAME_CLOSING:
  1167.                       internalFrameListener.internalFrameClosing(
  1168.                           (InternalFrameEvent)e);
  1169.                       doDefaultCloseAction();
  1170.                       return;
  1171.                   case InternalFrameEvent.INTERNAL_FRAME_CLOSED:
  1172.                       internalFrameListener.internalFrameClosed(
  1173.                           (InternalFrameEvent)e);
  1174.                       return;
  1175.                   case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED:
  1176.                       internalFrameListener.internalFrameIconified(
  1177.                           (InternalFrameEvent)e);
  1178.                       return;
  1179.                   case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED:
  1180.                       internalFrameListener.internalFrameDeiconified(
  1181.                           (InternalFrameEvent)e);
  1182.                       return;
  1183.                   case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED:
  1184.                       internalFrameListener.internalFrameActivated(
  1185.                           (InternalFrameEvent)e);
  1186.                       return;
  1187.                   case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED:
  1188.                       internalFrameListener.internalFrameDeactivated(
  1189.                           (InternalFrameEvent)e);
  1190.                       return;
  1191.                   default:
  1192.                       break;
  1193.                 }
  1194.             } else if (e.getID() == InternalFrameEvent.INTERNAL_FRAME_CLOSING) {
  1195.                 doDefaultCloseAction();
  1196.             }
  1197.         }
  1198.         super.processEvent(e);
  1199.     }
  1200.  
  1201.     /**
  1202.      * Sets the operation which will happen by default when
  1203.      * the user initiates a "close" on this window.
  1204.      * The possible choices are:
  1205.      * <p>
  1206.      * <ul>
  1207.      * <li>DO_NOTHING_ON_CLOSE - do not do anything - require the
  1208.      * program to handle the operation in the windowClosing
  1209.      * method of a registered InternalFrameListener object.
  1210.      * <li>HIDE_ON_CLOSE - automatically hide the window after
  1211.      * invoking any registered InternalFrameListener objects
  1212.      * <li>DISPOSE_ON_CLOSE - automatically hide and dispose the 
  1213.      * window after invoking any registered InternalFrameListener objects
  1214.      * </ul>
  1215.      * <p>
  1216.      * The value is set to HIDE_ON_CLOSE by default.
  1217.      * @see #addInternalFrameListener
  1218.      * @see #getDefaultCloseOperation
  1219.      */
  1220.     public void setDefaultCloseOperation(int operation) {
  1221.         this.defaultCloseOperation = operation;
  1222.     }
  1223.  
  1224.    /**
  1225.     * Returns the default operation which occurs when the user
  1226.     * initiates a "close" on this window.
  1227.     * @see #setDefaultCloseOperation
  1228.     */
  1229.     public int getDefaultCloseOperation() {
  1230.         return defaultCloseOperation;
  1231.     }
  1232.  
  1233.     /**
  1234.      * Causes subcomponents of this JInternalFrame to be laid out at their
  1235.      * preferred size.
  1236.      * @see       java.awt.Window#pack
  1237.      */
  1238.     public void pack() {
  1239.         Container parent = getParent();
  1240.         if (parent != null && parent.getPeer() == null) {
  1241.             parent.addNotify();
  1242.             addNotify();
  1243.         }
  1244.         setSize(getPreferredSize());
  1245.         validate();
  1246.     }
  1247.  
  1248.     /**
  1249.      * Shows this internal frame, and brings it to the front.
  1250.      * <p>
  1251.      * If this window is not yet visible, <code>show</code> 
  1252.      * makes it visible. If this window is already visible, 
  1253.      * then this method brings it to the front. 
  1254.      * @see       java.awt.Window#show
  1255.      * @see       java.awt.Window#toFront
  1256.      * @see       java.awt.Component#setVisible
  1257.      */
  1258.     public void show() {
  1259.         pack();
  1260.         if (isVisible()) {
  1261.         toFront();
  1262.     } else {
  1263.             super.show();
  1264.         }
  1265.         if (!isSelected()) {
  1266.             try {
  1267.                 setSelected(true);
  1268.             } catch (PropertyVetoException pve) {}
  1269.         }
  1270.     }
  1271.  
  1272.     /**
  1273.      * Disposes of this internal frame. If the frame is not already
  1274.      * closed, a frame-closing event is posted.
  1275.      */
  1276.     public void dispose() {
  1277.         if (isVisible()) {
  1278.             setVisible(false);
  1279.         }
  1280.         if (isSelected()) {
  1281.             try {
  1282.                 setSelected(false);
  1283.             } catch (PropertyVetoException pve) {}
  1284.         }
  1285.         if (!isClosed) {
  1286.             postInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED);
  1287.         }
  1288.     }
  1289.  
  1290.     /**
  1291.      * Brings this internal frame to the front.
  1292.      * Places this internal frame  at the top of the stacking order
  1293.      * and makes the corresponding adjustment to other visible windows.
  1294.      * @see       java.awt.Window#toFront
  1295.      * @see       #moveToFront
  1296.      */
  1297.     public void toFront() {
  1298.         moveToFront();
  1299.     }
  1300.  
  1301.     /**
  1302.      * Sends this internal frame to the back.
  1303.      * Places this internal frame  at the bottom of the stacking order
  1304.      * and makes the corresponding adjustment to other visible windows.
  1305.      * @see       java.awt.Window#toBack
  1306.      * @see       #moveToBack
  1307.      */
  1308.     public void toBack() {
  1309.         moveToBack();
  1310.     }
  1311.  
  1312.     /**
  1313.      * Gets the warning string that is displayed with this window. 
  1314.      * Since an internal frame is always secure (since it's fully
  1315.      * contained within a window which might need a warning string)
  1316.      * this method always returns null.
  1317.      * @return    null
  1318.      * @see       java.awt.Window#getWarningString
  1319.      */
  1320.     public final String getWarningString() {
  1321.         return null;
  1322.     }
  1323.  
  1324.  
  1325. /////////////////
  1326. // Mouse support
  1327. ////////////////
  1328.  
  1329.     /**
  1330.      * When inactive, mouse events are forwarded as appropriate either to 
  1331.      * the UI to activate the frame or to the underlying child component.
  1332.      *
  1333.      * In keeping with the MDI messaging model (which JInternalFrame
  1334.      * emulates), only the mousePressed event is forwarded to the UI
  1335.      * to activate the frame.  The mouseEntered, mouseMoved, and 
  1336.      * MouseExited events are forwarded to the underlying child
  1337.      * component, using methods derived from those in Container.
  1338.      * The other mouse events are purposely ignored, since they have
  1339.      * no meaning to either the frame or its children when the frame
  1340.      * is inactive.
  1341.      */
  1342.     public void mousePressed(MouseEvent e) {
  1343.         ((MouseListener)ui).mousePressed(e);
  1344.     }
  1345.     /** 
  1346.      * Forward the mouseEntered event to the underlying child container.
  1347.      * @see #mousePressed
  1348.      */
  1349.     public void mouseEntered(MouseEvent e) {
  1350.         forwardMouseEvent(e);
  1351.     }
  1352.     /** 
  1353.      * Forward the mouseMoved event to the underlying child container.
  1354.      * @see #mousePressed
  1355.      */
  1356.     public void mouseMoved(MouseEvent e) {
  1357.         forwardMouseEvent(e);
  1358.     }
  1359.     /** 
  1360.      * Forward the mouseExited event to the underlying child container.
  1361.      * @see #mousePressed
  1362.      */
  1363.     public void mouseExited(MouseEvent e) {
  1364.         forwardMouseEvent(e);
  1365.     }
  1366.     /** 
  1367.      * Ignore mouseClicked events.
  1368.      * @see #mousePressed
  1369.      */
  1370.     public void mouseClicked(MouseEvent e) {
  1371.     }
  1372.     /** 
  1373.      * Ignore mouseReleased events.
  1374.      * @see #mousePressed
  1375.      */
  1376.     public void mouseReleased(MouseEvent e) {
  1377.     }
  1378.     /** 
  1379.      * Ignore mouseDragged events.
  1380.      * @see #mousePressed
  1381.      */
  1382.     public void mouseDragged(MouseEvent e) {
  1383.     }
  1384.  
  1385.     /* 
  1386.      * Forward a mouse event to the current mouse target, setting it
  1387.      * if necessary.
  1388.      */
  1389.     private void forwardMouseEvent(MouseEvent e) {
  1390.         Component target = findComponentAt(getContentPane(), 
  1391.                                            e.getX(), e.getY());
  1392.         if (target != mouseEventTarget) {
  1393.             setMouseTarget(target, e);
  1394.         }
  1395.         retargetMouseEvent(e.getID(), e);
  1396.     }
  1397.  
  1398.     private Component mouseEventTarget = null;
  1399.  
  1400.     /*
  1401.      * Find the lightweight child component which corresponds to the
  1402.      * specified location.  This is similar to the new 1.2 API in
  1403.      * Container, but we need to run on 1.1.  The other changes are
  1404.      * due to Container.findComponentAt's use of package-private data.
  1405.      */
  1406.     private static Component findComponentAt(Container c, int x, int y) {
  1407.         if (!c.contains(x, y)) {
  1408.             return c;
  1409.         }
  1410.         int ncomponents = c.getComponentCount();
  1411.         Component component[] = c.getComponents();
  1412.         for (int i = 0 ; i < ncomponents ; i++) {
  1413.             Component comp = component[i];
  1414.             Point loc = comp.getLocation();
  1415.             if ((comp != null) && (comp.contains(x - loc.x, y - loc.y)) &&
  1416.                 (comp.getPeer() instanceof java.awt.peer.LightweightPeer) &&
  1417.                 (comp.isVisible() == true)) {
  1418.                 // found a component that intersects the point, see if there
  1419.                 // is a deeper possibility.
  1420.                 if (comp instanceof Container) {
  1421.                     Container child = (Container) comp;
  1422.                     Point childLoc = child.getLocation();
  1423.                     Component deeper = findComponentAt(child,
  1424.                         x - childLoc.x, y - childLoc.y);
  1425.                     if (deeper != null) {
  1426.                         return deeper;
  1427.                     }
  1428.                 } else {
  1429.                     return comp;
  1430.                 }
  1431.             }
  1432.         }
  1433.         return c;
  1434.     }
  1435.  
  1436.     /*
  1437.      * Set the child component to which events are forwarded, and
  1438.      * synthesize the appropriate mouseEntered and mouseExited events.
  1439.      */
  1440.     private void setMouseTarget(Component target, MouseEvent e) {
  1441.         if (mouseEventTarget != null) {
  1442.             retargetMouseEvent(MouseEvent.MOUSE_EXITED, e);
  1443.         }
  1444.         mouseEventTarget = target;
  1445.         if (mouseEventTarget != null) {
  1446.             retargetMouseEvent(MouseEvent.MOUSE_ENTERED, e);
  1447.         }
  1448.     }
  1449.  
  1450.     /* 
  1451.      * Dispatch an event clone, retargeted for the current mouse target.
  1452.      */
  1453.     void retargetMouseEvent(int id, MouseEvent e) {
  1454.         MouseEvent retargeted = new MouseEvent(mouseEventTarget, 
  1455.                                                id, 
  1456.                                                e.getWhen(), 
  1457.                                                e.getModifiers(),
  1458.                                                e.getX(), 
  1459.                                                e.getY(), 
  1460.                                                e.getClickCount(), 
  1461.                                                e.isPopupTrigger());
  1462.         mouseEventTarget.dispatchEvent(retargeted);
  1463.     }
  1464.  
  1465.     /**
  1466.      * Invoked when a maximized JInternalFrame's parent's size changes.
  1467.      */
  1468.     public void componentResized(ComponentEvent e) {
  1469.         Dimension d = ((Component)e.getSource()).getSize();
  1470.         setBounds(0, 0, d.width, d.height);
  1471.         validate();
  1472.     }
  1473.  
  1474.     /* Unused */
  1475.     public void componentMoved(ComponentEvent e) {}
  1476.     /* Unused */
  1477.     public void componentShown(ComponentEvent e) {}
  1478.     /* Unused */
  1479.     public void componentHidden(ComponentEvent e) {}
  1480.  
  1481. /////////////////
  1482. // Accessibility support
  1483. ////////////////
  1484.  
  1485.     /**
  1486.      * Get the AccessibleContext associated with this JComponent
  1487.      *
  1488.      * @return the AccessibleContext of this JComponent
  1489.      */
  1490.     public AccessibleContext getAccessibleContext() {
  1491.         if (accessibleContext == null) {
  1492.             accessibleContext = new AccessibleJInternalFrame();
  1493.         }
  1494.         return accessibleContext;
  1495.     }
  1496.  
  1497.     /**
  1498.      * The class used to obtain the accessible role for this object.
  1499.      * <p>
  1500.      * Warning: serialized objects of this class will not be compatible with
  1501.      * future swing releases.  The current serialization support is appropriate
  1502.      * for short term storage or RMI between Swing1.0 applications.  It will
  1503.      * not be possible to load serialized Swing1.0 objects with future releases
  1504.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1505.      * baseline for the serialized form of Swing objects.
  1506.      */
  1507.     protected class AccessibleJInternalFrame extends AccessibleJComponent 
  1508.         implements AccessibleValue {
  1509.  
  1510.         /**
  1511.          * Get the accessible name of this object.  This should almost never
  1512.          * return java.awt.Component.getName(), as that generally isn't
  1513.          * a localized name, and doesn't have meaning for the user.  If the
  1514.          * object is fundamentally a text object (e.g. a menu item), the
  1515.          * accessible name should be the text of the object (e.g. "save").
  1516.          * If the object has a tooltip, the tooltip text may also be an
  1517.          * appropriate String to return.
  1518.          *
  1519.          * @return the localized name of the object -- can be null if this 
  1520.          * object does not have a name
  1521.          * @see #setAccessibleName
  1522.          */
  1523.         public String getAccessibleName() {
  1524.             if (accessibleName != null) {
  1525.                 return accessibleName;
  1526.             } else {
  1527.                 return getTitle();
  1528.             }
  1529.         }
  1530.  
  1531.         /**
  1532.          * Get the role of this object.
  1533.          *
  1534.          * @return an instance of AccessibleRole describing the role of the 
  1535.          * object
  1536.          * @see AccessibleRole
  1537.          */
  1538.         public AccessibleRole getAccessibleRole() {
  1539.             return AccessibleRole.INTERNAL_FRAME;
  1540.         }
  1541.  
  1542.         /**
  1543.          * Get the AccessibleValue associated with this object if one
  1544.          * exists.  Otherwise return null.
  1545.          */
  1546.         public AccessibleValue getAccessibleValue() {
  1547.             return this;
  1548.         }
  1549.  
  1550.  
  1551.         //
  1552.         // AccessibleValue methods
  1553.         //
  1554.  
  1555.         /**
  1556.          * Get the value of this object as a Number.
  1557.          *
  1558.          * @return value of the object -- can be null if this object does not
  1559.          * have a value
  1560.          */
  1561.         public Number getCurrentAccessibleValue() {
  1562.             return new Integer(getLayer());
  1563.         }
  1564.  
  1565.         /**
  1566.          * Set the value of this object as a Number.
  1567.          *
  1568.          * @return True if the value was set.
  1569.          */
  1570.         public boolean setCurrentAccessibleValue(Number n) {
  1571.             if (n instanceof Integer) {
  1572.                 setLayer((Integer) n);
  1573.                 return true;
  1574.             } else {
  1575.                 return false;
  1576.             }
  1577.         }
  1578.  
  1579.         /**
  1580.          * Get the minimum value of this object as a Number.
  1581.          *
  1582.          * @return Minimum value of the object; null if this object does not
  1583.          * have a minimum value
  1584.          */
  1585.         public Number getMinimumAccessibleValue() {
  1586.             return new Integer(Integer.MIN_VALUE);
  1587.         }
  1588.  
  1589.         /**
  1590.          * Get the maximum value of this object as a Number.
  1591.          *
  1592.          * @return Maximum value of the object; null if this object does not
  1593.          * have a maximum value
  1594.          */
  1595.         public Number getMaximumAccessibleValue() {
  1596.             return new Integer(Integer.MAX_VALUE);
  1597.         }
  1598.  
  1599.     } // AccessibleJInternalFrame
  1600.  
  1601.     private static class MyEventMulticaster extends AWTEventMulticaster 
  1602.             implements InternalFrameListener {
  1603.         public MyEventMulticaster(EventListener a,
  1604.                                   EventListener b) {
  1605.             super(a, b);
  1606.         }
  1607.  
  1608.         public static InternalFrameListener add(InternalFrameListener a, 
  1609.                                                 InternalFrameListener b) {
  1610.             return (InternalFrameListener)addInternal(a, b);
  1611.         }
  1612.  
  1613.         public static InternalFrameListener remove(InternalFrameListener l, 
  1614.                                                    InternalFrameListener oldl){
  1615.             return (InternalFrameListener) removeInternal(l, oldl);
  1616.         }
  1617.  
  1618.         public void internalFrameOpened(InternalFrameEvent e) {
  1619.             ((InternalFrameListener)a).internalFrameOpened(e);
  1620.             ((InternalFrameListener)b).internalFrameOpened(e);
  1621.         }
  1622.  
  1623.         public void internalFrameClosing(InternalFrameEvent e) {
  1624.             ((InternalFrameListener)a).internalFrameClosing(e);
  1625.             ((InternalFrameListener)b).internalFrameClosing(e);
  1626.         }
  1627.  
  1628.         public void internalFrameClosed(InternalFrameEvent e) {
  1629.             ((InternalFrameListener)a).internalFrameClosed(e);
  1630.             ((InternalFrameListener)b).internalFrameClosed(e);
  1631.         }
  1632.  
  1633.         public void internalFrameIconified(InternalFrameEvent e) {
  1634.             ((InternalFrameListener)a).internalFrameIconified(e);
  1635.             ((InternalFrameListener)b).internalFrameIconified(e);
  1636.         }
  1637.  
  1638.         public void internalFrameDeiconified(InternalFrameEvent e) {
  1639.             ((InternalFrameListener)a).internalFrameDeiconified(e);
  1640.             ((InternalFrameListener)b).internalFrameDeiconified(e);
  1641.         }
  1642.  
  1643.         public void internalFrameActivated(InternalFrameEvent e) {
  1644.             ((InternalFrameListener)a).internalFrameActivated(e);
  1645.             ((InternalFrameListener)b).internalFrameActivated(e);
  1646.         }
  1647.  
  1648.         public void internalFrameDeactivated(InternalFrameEvent e) {
  1649.             ((InternalFrameListener)a).internalFrameDeactivated(e);
  1650.             ((InternalFrameListener)b).internalFrameDeactivated(e);
  1651.         }
  1652.  
  1653.         protected static EventListener addInternal(EventListener a, 
  1654.                                                    EventListener b) {
  1655.             if (a == null)  return b;
  1656.             if (b == null)  return a;
  1657.             return new MyEventMulticaster(a, b);
  1658.         }
  1659.     }
  1660.  
  1661.     /**
  1662.      * This component represents an iconified version of a JInternalFrame.
  1663.      * This API should NOT BE USED by Swing applications, as it will go
  1664.      * away in future versions of Swing as its functionality is moved into
  1665.      * JInternalFrame.  This class is public only so that UI objects can
  1666.      * display a desktop icon.  If an application wants to display a
  1667.      * desktop icon, it should create a JInternalFrame instance and
  1668.      * iconify it.
  1669.      * <p>
  1670.      * Warning: serialized objects of this class will not be compatible with
  1671.      * future swing releases.  The current serialization support is appropriate 
  1672.      * for short term storage or RMI between Swing1.0 applications.  It will
  1673.      * not be possible to load serialized Swing1.0 objects with future releases
  1674.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1675.      * baseline for the serialized form of Swing objects.
  1676.      *
  1677.      * @author David Kloba
  1678.      */
  1679.     static public class JDesktopIcon extends JComponent implements Accessible
  1680.     {
  1681.         JInternalFrame internalFrame;
  1682.  
  1683.         /** Create an icon for an internal frame
  1684.          * @param f  the JInternalFrame for which the icon is created
  1685.          */
  1686.         public JDesktopIcon(JInternalFrame f) {
  1687.             setInternalFrame(f);
  1688.             updateUI();
  1689.         }
  1690.  
  1691.         /**
  1692.          * Returns the L&F object that renders this component.
  1693.          *
  1694.          * @return the DesktopIconUI object that renders this component
  1695.          */
  1696.         public DesktopIconUI getUI() {
  1697.             return (DesktopIconUI)ui;
  1698.         }
  1699.  
  1700.         /**
  1701.          * Sets the L&F object that renders this component.
  1702.          *
  1703.          * @param ui  the DesktopIconUI L&F object
  1704.          * @see UIDefaults#getUI
  1705.          */
  1706.         public void setUI(DesktopIconUI ui) {
  1707.             super.setUI(ui);
  1708.         }
  1709.  
  1710.         /** 
  1711.          * Returns the JInternalFrame that this DesktopIcon is 
  1712.          * associated with. 
  1713.          * @return the JInternalFrame this icon is associated with 
  1714.          */
  1715.         public JInternalFrame getInternalFrame() {
  1716.             return internalFrame;
  1717.         }
  1718.  
  1719.         /** 
  1720.          * Sets the JInternalFrame that this DesktopIcon is 
  1721.          * associated with.
  1722.          * @param f  the JInternalFrame this icon is associated with 
  1723.          */
  1724.         public void setInternalFrame(JInternalFrame f) {
  1725.             internalFrame = f;
  1726.         }
  1727.  
  1728.         /** Convience method to ask the icon for the Desktop object
  1729.          * it belongs to.
  1730.          * @return the JDesktopPane that contains this icon's internal
  1731.          *         frame, or null if none found
  1732.          */
  1733.         public JDesktopPane getDesktopPane() {
  1734.             if(getInternalFrame() != null)
  1735.                 return getInternalFrame().getDesktopPane();
  1736.             return null;
  1737.         }
  1738.  
  1739.         /**
  1740.          * Notification from the UIManager that the L&F has changed. 
  1741.          * Replaces the current UI object with the latest version from the 
  1742.          * UIManager.
  1743.          *
  1744.          * @see JComponent#updateUI
  1745.          */
  1746.         public void updateUI() {
  1747.             boolean hadUI = (ui != null);
  1748.             setUI((DesktopIconUI)UIManager.getUI(this));
  1749.             invalidate();
  1750.  
  1751.             Dimension r = getPreferredSize();
  1752.             setSize(r.width, r.height);
  1753.             
  1754.             if (internalFrame != null) {
  1755.                 SwingUtilities.updateComponentTreeUI(internalFrame);
  1756.             }
  1757.         }
  1758.  
  1759.         /* This method is called if updateUI was called on the associated
  1760.          * JInternalFrame.  It's necessary to avoid infinite recursion.
  1761.          */
  1762.         void updateUIWhenHidden() {
  1763.             /* Update this UI and any associated internal frame */
  1764.             setUI((DesktopIconUI)UIManager.getUI(this));
  1765.             invalidate();
  1766.             Component[] children = getComponents();
  1767.             if (children != null) {
  1768.                 for(int i = 0; i < children.length; i++) {
  1769.                     SwingUtilities.updateComponentTreeUI(children[i]);
  1770.                 }
  1771.             }
  1772.         }
  1773.  
  1774.         /**
  1775.          * Returns the name of the L&F class that renders this component.
  1776.          *
  1777.          * @return "DesktopIconUI"
  1778.          * @see JComponent#getUIClassID
  1779.          * @see UIDefaults#getUI
  1780.          */
  1781.         public String getUIClassID() {
  1782.             return "DesktopIconUI";
  1783.         }
  1784.  
  1785.        /////////////////
  1786.        // Accessibility support
  1787.        ////////////////
  1788.  
  1789.         /**
  1790.          * Get the AccessibleContext associated with this JComponent
  1791.          *
  1792.          * @return the AccessibleContext of this JComponent
  1793.          */
  1794.         public AccessibleContext getAccessibleContext() {
  1795.             if (accessibleContext == null) {
  1796.                 accessibleContext = new AccessibleJDesktopIcon();
  1797.             }
  1798.             return accessibleContext;
  1799.         }
  1800.  
  1801.         /**
  1802.          * The class used to obtain the accessible role for this object.
  1803.          * <p>
  1804.          * Warning: serialized objects of this class will not be compatible with
  1805.          * future swing releases.  The current serialization support is appropriate
  1806.          * for short term storage or RMI between Swing1.0 applications.  It will
  1807.          * not be possible to load serialized Swing1.0 objects with future releases
  1808.          * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1809.          * baseline for the serialized form of Swing objects.
  1810.          */
  1811.         protected class AccessibleJDesktopIcon extends AccessibleJComponent 
  1812.             implements AccessibleValue {
  1813.  
  1814.             /**
  1815.              * Get the role of this object.
  1816.              *
  1817.              * @return an instance of AccessibleRole describing the role of the 
  1818.              * object
  1819.              * @see AccessibleRole
  1820.              */
  1821.             public AccessibleRole getAccessibleRole() {
  1822.                 return AccessibleRole.DESKTOP_ICON;
  1823.             }
  1824.  
  1825.             /**
  1826.              * Get the AccessibleValue associated with this object if one
  1827.              * exists.  Otherwise return null.
  1828.              */
  1829.             public AccessibleValue getAccessibleValue() {
  1830.                 return this;
  1831.             }
  1832.  
  1833.             //
  1834.             // AccessibleValue methods
  1835.             //
  1836.  
  1837.             /**
  1838.              * Get the value of this object as a Number.
  1839.              *
  1840.              * @return value of the object -- can be null if this object does not
  1841.              * have a value
  1842.              */
  1843.             public Number getCurrentAccessibleValue() {
  1844.                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1845.                 AccessibleValue v = a.getAccessibleValue();
  1846.                 if (v != null) {
  1847.                     return v.getCurrentAccessibleValue();
  1848.                 } else {
  1849.                     return null;
  1850.                 }
  1851.             }
  1852.  
  1853.             /**
  1854.              * Set the value of this object as a Number.
  1855.              *
  1856.              * @return True if the value was set.
  1857.              */
  1858.             public boolean setCurrentAccessibleValue(Number n) {
  1859.                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1860.                 AccessibleValue v = a.getAccessibleValue();
  1861.                 if (v != null) {
  1862.                     return v.setCurrentAccessibleValue(n);
  1863.                 } else {
  1864.                     return false;
  1865.                 }
  1866.             }
  1867.  
  1868.             /**
  1869.              * Get the minimum value of this object as a Number.
  1870.              *
  1871.              * @return Minimum value of the object; null if this object does not
  1872.              * have a minimum value
  1873.              */
  1874.             public Number getMinimumAccessibleValue() {
  1875.                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1876.                 if (a instanceof AccessibleValue) {
  1877.                     return ((AccessibleValue)a).getMinimumAccessibleValue();
  1878.                 } else {
  1879.                     return null;
  1880.                 }
  1881.             }
  1882.  
  1883.             /**
  1884.              * Get the maximum value of this object as a Number.
  1885.              *
  1886.              * @return Maximum value of the object; null if this object does not
  1887.              * have a maximum value
  1888.              */
  1889.             public Number getMaximumAccessibleValue() {
  1890.                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1891.                 if (a instanceof AccessibleValue) {
  1892.                     return ((AccessibleValue)a).getMaximumAccessibleValue();
  1893.                 } else {
  1894.                     return null;
  1895.                 }
  1896.             }
  1897.  
  1898.         } // AccessibleJDesktopIcon
  1899.     }
  1900. }
  1901.